using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using Jy.Abp.Services;
using Microsoft.AspNetCore.Mvc.Controllers;
using Microsoft.IdentityModel.Tokens;

namespace Jy.Abp.AspNetCore.Swagger;

public static class SwaggerHelper
{
    private static readonly ConcurrentDictionary<string, IEnumerable<ServiceGroupAttribute>> _actionGroupAttrs = new();

    public static string DefaultDocName = "all";
    public static string ApplicationName = "web";
    public static Dictionary<string, string> Groups = new Dictionary<string, string>();

    /// <summary>
    /// 自定义分组检测方法
    /// </summary>
    public static Func<string, ControllerActionDescriptor, bool> CustomGroupChecker { get; set; }

    /// <summary>
    /// 获取接口对应的验证attr
    /// </summary>
    private static IEnumerable<ServiceGroupAttribute> GetGroupAttrs(ControllerActionDescriptor actionDescriptor)
    {
        return _actionGroupAttrs.GetOrAdd(GetCacheKey(actionDescriptor), key =>
        {
            var attrs = new List<ServiceGroupAttribute>();
            
            // 获取方法级别的特性
            var actionAttr = actionDescriptor.MethodInfo?.GetCustomAttribute<ServiceGroupAttribute>();
            if (actionAttr != null)
                attrs.Add(actionAttr);
                
            // 获取控制器级别的特性
            var controllerAttr = actionDescriptor.ControllerTypeInfo?.GetCustomAttribute<ServiceGroupAttribute>();
            if (controllerAttr != null)
                attrs.Add(controllerAttr);
                
            return attrs.DistinctBy(t => t.Group).ToList();
        });
    }

    /// <summary>
    /// 生成缓存键
    /// </summary>
    private static string GetCacheKey(ControllerActionDescriptor actionDescriptor)
    {
        return $"{actionDescriptor.ControllerTypeInfo.FullName}.{actionDescriptor.MethodInfo.Name}";
    }

    public static void Init(string applicationName)
    {
        ApplicationName = applicationName;
        Groups.Add(DefaultDocName, $"{ApplicationName} API");
        foreach (var pt in ServiceGroupAttribute.Groups)
        {
            Groups.Add($"{pt}", $"{pt} API");
        }
    }

    /// <summary>
    /// 检测当前doc是否有显示此action api的权限
    /// </summary>
    public static bool CheckGroup(
        string docName,
        ControllerActionDescriptor action)
    {
        // 优先使用自定义检测方法
        if (CustomGroupChecker != null)
        {
            return CustomGroupChecker(docName, action);
        }

        // 默认检测逻辑
        if (docName != DefaultDocName)
        {
            var attrs = GetGroupAttrs(action);
            return attrs.Any(t => t.Group == docName);
        }
        return true;
    }
}

